#ifndef __UTILS_H_
#define __UTILS_H_

#include <stdbool.h>
#include "chunk.h"
#include "lichstor.h"
#include "etcd.h"

#define ALLOCATE_THREAD_MAX 100
#define ALLOCATE_THREAD_DEFAULT 1
#define ALLOCATE_PIPE_MAX 3000
#define ALLOCATE_PIPE_DEFAULT 3000

typedef enum {
        VOL_INFO_NORMAL    = 0,
        VOL_INFO_ALLOCATE  = 1,
        VOL_INFO_FULL      = 2,
} lichbd_vol_info_t;

typedef struct {
        struct list_head hook;
        nid_t master;
        uint64_t taskid;
        chkinfo_t chkinfo[0];
} scan_entry_t;

typedef struct {
        char *path;
        int thread;
        int deep;
        int verbose;
} recovery_t;

typedef enum {
        DEFAULT_FORMAT = 0,
        JSON_FORMAT,
        XML_FORMAT,
} output_format_t;

static inline int check_nodes(char nodes[][1024], int count)
{
        int i, j;

        if (count == 1)
                return 0;

        for (i = 0; i < count; i++) {
                for (j = i + 1; j < count; j++) {
                        if(strcmp(nodes[i] , nodes[j]) == 0)  {
                            return 1;
                        };
                }
        }

        return 0;
}

/* clone.c */
int clone_local2lun(const char *from, const char *to, int replace);
int clone_lun2lun1(const char *from, const char *to);
int clone_lun2lun(const char *from, const char *to);
int clone_lun2local(const char *from, const char *to);
int append_local2lun(const char *from, const char *to);
int clone_init(int thread);

/* recover.c */
int recover_parallel_get(int *_parallel, int *_expdata, int *_parallel_real);
int recover_queue(msgqueue_t *queue, int total, int parallel, int *needretry, int *recover_succ);
int recover_pop(msgqueue_t *queue, int count, struct list_head *list);
int recover_replica_queue(msgqueue_t *queue, int total, int parallels, int *needretry);
int recover_chkinfo_losted(const chkinfo_t *chkinfo);

/* balance.c */
int parallel_get(int *_parallel, char *parallel_path, int *_expdata,
                char *expdata_path, int *_parallel_real, int parallel_default);
int balance_parallel_get(int *parallel, int *expdata, int *parallel_real);
int balance(const chkid_t *id);

/*  not use */
int chunk_check_node(const chkinfo_t *chkinfo, int full);
int iterate_all(const char *path, int verbose, msgqueue_t *recover,
                uint64_t *recover_count, msgqueue_t *lost, uint64_t *lost_count, int full);

int lich_chunktable_scanmeta(const char **path, int count, int idx, int recover,
                int *recover_total, int *recover_need, int *recover_succ);
int lich_chunktable_recover_replica(const char **path, int count, int idx);
int lich_meta_recover_replica(chkinfo_t *chkinfo);

/* scan.c */
int lich_scan(const char *path, int verbose, int recover, int full);

/* recovery.c */
int recovery_bypath(void *pool, void *arg);
int recovery_scan(void *pool, void *arg);


/* attr.c */
int lich_xattr_set(const char *pool, const char *path, const char *key, const char *value);
int lich_xattr_remove(const char *pool, const char *path, const char *key);
int lich_xattr_get_buf(const char *pool, const char *path, const char *key, char *buf, int *buflen);
int lich_xattr_get(const char *pool, const char *path, const char *key, int output_format);
int lich_xattr_list(const char *pool, const char *path);

/* copy.c */
int stor_copy(const char *pool, const char *from, const char *to, int multi, bool thin, int p);
int stor_copy_with_area(const char *fpool, const char *from, const char *tpool, const char *to,
                int multi, bool thin, int p, const char *site_name, int volume_format);
int stor_copy_offset(const char *pool, const char *from, const char *to, int idx);
int stor_apply(const char *pool, const char *from, const char *to);

int stor_stat_multi(const nid_t *nid, const fileid_t *fileid, filestat_t *filestat, int multi, int full);
int file_md5sum(const char *pool, const fileid_t *fileid, const char *path);
int file_md5sum_mult_thread(const char *pool, const fileid_t *fileid, const char *path);

/* spare.c */
int spare_value2size(const char *pool, const char *value, uint64_t *size);
int utils_spare_policy(const char *pool);

/* hierarch.c */
int lich_tier_set(const char *pool, const char *name, int tier, int verbose);
int lich_tier_get(const char *pool, const char *name, int verbose);

int lich_priority_set(const char *pool, const char *name, int tier, int verbose, int pithy);
int lich_priority_get(const char *pool, const char *name, int verbose, int pithy);

int lich_localize_set(const char *pool, const char *name, int num);
int lich_localize_get(const char *pool, const char *name);

int lich_writeback_set(const char *pool, const char *name, int num);
int lich_writeback_get(const char *pool, const char *name);

int lich_multpath_set(const char *pool, const char *name, int num);
int lich_multpath_get(const char *pool, const char *name);

/* utils.c */
int lich_readraw_set(const char *pool, const char *name, int num);
int lich_readraw_get(const char *pool, const char *name);

int utils_mkdir(const char *pool, const char *dir, int parents, ec_t *ec, const char *site);
int utils_rmdir(const char *pool, const char *dir);
int utils_list(const char *pool, const char *dir, int flag, int output_format);
int utils_iterator(const char *pool, const char *dir, func_int3_t func, void *arg);

int utils_touch(const char *pool, const char *file, int priority);
int utils_touch_with_area(const char *pool, const char *file, vol_param_t *param);
int utils_rmvol(const char *pool, const char *file, int force);

int utils_truncate(const char *pool, const char *path, size_t size);
int utils_rename(const char *pool, const char *from, const char *to);
int utils_write(const char *pool, const char *from, const char *to, uint64_t offset);
int utils_duplicate(const char *src_pool, const char *from, const char *dest_pool, const char *to,
                int p, const char *storage_area, int type);
int utils_migrate_lock(etcd_lock_t *lock, const char *key);
void utils_migrate_unlock(etcd_lock_t *lock);
int utils_migrate(const char *src_pool, char *from, const char *dest_pool, char *to,
                int p, char *storage_area, int force);

int utils_fsstat(const char *path);
int utils_list_storagearea();
int utils_check_storagearea(const char * _site);
int utils_stat(const char *pool, const char *path, int format);
int utils_find(const char *pool, const char *path, const char *name, int recursive);
int utils_cat(const char *pool, const char *path, uint64_t offset, __off_t length);
int utils_get_size(const char *_str, uint64_t *_size);
int utils_md5sum(const char *pool, const char *path, int mult_thread);
int utils_connection(const char *pool, const char *path);
int utils_check_connection(const char *pool, const char *file, fileid_t *fid);
int utils_info(const char *pool, const char *path, int full, int verbose);
void utils_info_print(fileid_t *fileid, nid_t *nid, filestat_t *filestat, int full);
int utils_chunkinfo(const char *pool, const char *path, int verbose, int pithy);

int utils_snapshot_create(const char *pool, const char *name, int force, int p);
int utils_snapshot_remove(const char *pool, const char *name, int force);
int utils_snapshot_rollback(const char *pool, const char *name);

int utils_snapshot_protect(const char *pool, const char *name);
int utils_snapshot_unprotect(const char *pool, const char *name);
int utils_snapshot_protect_set(const char *pool, const char *name, int num);
int utils_snapshot_protect_get(const char *pool, const char *name);

int utils_snapshot_list(const char *pool, const char *name, int all, int format, int verbose);
int utils_snapshot_clone(const char *src_pool, const char *name, const char *dest_pool, const char *to, int p);
int utils_snapshot_flat(const char *pool, const char *name);
int utils_snapshot_copy(const char *pool, const char *name, const char *to, const char *idx);

int utils_snapshot_diff(const char *pool, const char *name, const char *to, const char *idx, const int json);
int utils_snapshot_cat(const char *pool, const char *name);
int utils_allocate(const char *pool, const char *path, int pipeline, int concurrent, int fill);

int utils_pool_list(int verbose);
int utils_pool_create(const char *pool);
int utils_pool_remove(const char *pool);
int utils_pool_drop(const char *pool);
int utils_snapshot_check_protect(const char *pool, const char *path, int *protect);
int utils_volume_has_protected_snapshot(const char *pool, const char *name);
int utils_check_snapshot_isempty(const char *pool, const char *file);

// chap
int lich_auth_set(char *key, char *value);
int lich_auth_remove(char *key);
int lich_auth_update(char *key, char *value);
int lich_auth_list();
int lich_auth_get(char *key);

#endif /* __UTILS_H_ */
